<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Amqp\Producers\SendRecordProducers;
use App\CustHub\Constants\MsgTypeConstants;
use App\CustHub\Constants\SendConfigConstants;
use App\CustHub\Constants\SmartPushSchemeStatusConstants;
use App\CustHub\Constants\SmartPushSchemeSubStatusConstants;
use App\CustHub\Constants\SmartPushSchemeTypeConstants;
use App\CustHub\Dto\SendRecordProducersDto;
use App\CustHub\Helpers\TagReplacer;
use App\CustHub\Mapper\ChSmartPushSchemeMapper;
use App\CustHub\Mapper\ChSmartPushSchemeSubTaskMapper;
use App\CustHub\Model\ChContact;
use Carbon\Carbon;
use Hyperf\Amqp\Producer;
use Hyperf\Database\Model\Builder;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;

class ChSmartPushSchemeSubService extends AbstractService
{
    public $mapper;

    #[Inject]
    protected ChSmartPushSchemeMapper $schemeMapper;

    public function __construct(ChSmartPushSchemeSubTaskMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    /**
     * 创建子任务
     * @param array $data
     * @return void
     */
    public function createTask(array $data): void
    {
        $taskId = $data['scheme_id'];
        $info = $this->schemeMapper->findById($taskId);
        if(empty($info)){
            return;
        }
        //受众配置
        $audCfg = $info['aud_cfg'];
        //机器人id
        $robotIds = $info->robots()->pluck('robot_id')->toArray();
        //满足条件的用户
        $contactData = $this->getQualifiedContactList($robotIds,$audCfg);
        $status = SmartPushSchemeStatusConstants::WAITING;

        if($contactData->isEmpty()){
            //单次发送的情况下查询不到满足条件的用户 任务完成
            $subStatus = SmartPushSchemeSubStatusConstants::WAITING;
            if($info['type'] == SmartPushSchemeTypeConstants::TIMING_SINGLE && time() >= strtotime($info->begin_time)){
                $status = SmartPushSchemeStatusConstants::COMPLETED;
                $subStatus = SmartPushSchemeSubStatusConstants::COMPLETED;
            }
            foreach ($robotIds as $robotId){
                $subData = [
                    'scheme_id' => $info->id,
                    'robot_id' => $robotId,
                    'contact_count' => 0,
                    'day' => Carbon::now()->toDateString(),
                    'content' => $info->content,
                    'status' => $subStatus
                ];
                $this->mapper->save($subData);
            }
            $contact_count = 0;
        }else{
            $contactMap = $contactData->groupBy('robot_id')->toArray();
            foreach ($contactMap as $robotId =>$contactList){
                $subData = [
                    'scheme_id' => $info->id,
                    'robot_id' => $robotId,
                    'contact_count' => count($contactList),
                    'day' => Carbon::now()->toDateString(),
                    'content' => $info->content,
                    'status' => SmartPushSchemeSubStatusConstants::WAITING
                ];
                $subSchemeId = $this->mapper->save($subData);
                $recordData = [];
                foreach ($contactList as $item){

                    $content = $info->content;
                    foreach ($content as $ck=>$contentItem){
                        if($contentItem['msg_type'] == MsgTypeConstants::TEXT){
                            $content[$ck]['content'] = TagReplacer::replaceTags($contentItem['content'],[
                                'call_name_nickname' => !empty($item['call_name']) ? $item['call_name'] : $item['nickname'],
                            ]);
                        }
                    }

                    $recordData[] = [
                        'uid' => $info->uid,
                        'main_uid' => $info->main_uid,
                        'task_id' => $taskId,
                        'sub_task_id' => $subSchemeId,
                        'robot_id' => $robotId,
                        'to_id' => $item['user_id'],
                        'trigger_time' => time(),
                        'start_time' => strtotime($info->begin_time),
                        'content' => $content,
                        'msg_total_count' => count($info->content),
                        'type' => SendConfigConstants::SMART_PUSH,
                    ];
                }

                container()->get(Producer::class)->produce(new SendRecordProducers(
                    (new SendRecordProducersDto())
                        ->setMainUid($info->main_uid)
                        ->setUid($info->uid)
                        ->setTaskId($taskId)
                        ->setSubTaskId($subSchemeId)
                        ->setType(SendConfigConstants::SMART_PUSH)
                        ->setRecordData($recordData)
                ));
            }
            $contact_count = $contactData->count();
        }


        //变更任务状态
        $this->schemeMapper->model::query()->where('id',$info->id)->update([
            'status' => $status,
            'contact_count' => $contact_count
        ]);
    }

    /**
     * 获取符合筛选条件的客户列表
     * @param array $robotIds
     * @param array $audCfg
     * @return \Hyperf\Database\Model\Collection|array
     */
    public function getQualifiedContactList(array $robotIds,array $audCfg,array $isSendUserIds = []): \Hyperf\Database\Model\Collection|array
    {
        $query = ChContact::query();
        $query->whereIn('robot_id',$robotIds);

        if(!empty($isSendUserIds)){
            $query->whereNotIn('user_id',$isSendUserIds);
        }

        $op = $audCfg['cond'] == 'or' ? 'orWhere' : "where";

        $items = $audCfg['items'];
        $query->where(function ($query) use ($op,$items){
            foreach ($items as $item){
                $query->{$op}(function ($query) use ($item){
                    $op = $item['op']  == 'or' ? 'orWhere' : "where";
                    $items = $item['items'];
                    foreach ($items as $value){
                        $query->{$op}(function ($query) use ($value){
                            $this->getFilter($query,$value);
                        });
                    }
                });
            }
        });

        $result = $query->get();
        return $result;
    }

    public function getFilter(Builder &$query,$item): void
    {
        $op = $item['op'];
        $value = $item['value'];
        switch ($item['event']){
            case "corp_tag":
                //企业标签
                if($op == 'in'){
                    //包含
                    $query->whereHas('corpTags', function ($query) use ($value) {
                        $query->whereIn('corp_tag_id', $value);
                    });
                }else{
                    //不包含
                    $query->whereHas('corpTags', function ($query) use ($value) {
                        $query->whereNotIn('corp_tag_id', $value);
                    });
                }
                break;
            case "smart_tag":
                //智能标签
                if($op == 'in'){
                    //包含
                    $query->whereHas('smartTags', function ($query) use ($value) {
                        $query->whereIn('smart_tag_id', $value);
                    });
                }else{
                    //不包含
                    $query->whereHas('smartTags', function ($query) use ($value) {
                        $query->whereNotIn('smart_tag_id', $value);
                    });
                }
                break;
            case "gender":
                //性别
                if($op == 'in'){
                    $query->whereIn('gender',$value);
                }else{
                    $query->whereNotIn("gender",$value);
                }
                break;
            case "source":
                //来源
                if($op == 'in'){
                    $query->whereIn('source',$value);
                }else{
                    $query->whereNotIn("source",$value);
                }
                break;
            case "created_at":
                //添加时间
                $startTime = strtotime($value['start_time']);
                $endTime = strtotime($value['end_time']);
                switch ($op){
                    case 'later':
                        $query->where('add_customer_time','<',$startTime);
                        break;
                    case 'earlier':
                        $query->where('add_customer_time','>',$startTime);
                        break;
                    case 'range_within':
                        $query->whereBetween('add_customer_time',[$startTime,$endTime]);
                        break;
                    case 'out_of_range':
                        $query->whereNotBetween('add_customer_time',[$startTime,$endTime]);
                        break;
                    default:
                        break;
                }
                break;
            case 'in_room':
                //在群内
                $query->whereHas('roomMember', function ($query) use ($value) {
                    $query->whereIn('room_wxid', $value);
                });
                break;
            case 'quite_room':
                //不在群内
                $query->whereHas('roomMember', function ($query) use ($value) {
                    $query->whereIn('room_wxid', $value);
                });
                break;
            case 'make_time':
                //成为好友时长
                $val = $value['val'];
                $unit = $value['unit'];
                switch ($unit){
                    case 0:
                        $thresholdTimestamp = Carbon::now()->subDays($val)->timestamp;
                        $endTime =  Carbon::now()->subDays($val - 1)->timestamp;
                        break;
                    case 1:
                        $thresholdTimestamp = Carbon::now()->subHours($val)->timestamp;
                        $endTime =  Carbon::now()->subHours($val - 1)->timestamp;
                        break;
                    default:
                        $thresholdTimestamp = Carbon::now()->subMinutes($val)->timestamp;
                        $endTime =  Carbon::now()->subMinutes($val - 1)->timestamp;
                        break;
                }

                switch ($op){
                    case "greater":
                        //大于
                        $query->where('add_customer_time', '>', $thresholdTimestamp);
                        break;
                    case "equal":
                        //等于
                        $query->whereBetween('created_at', [
                            $thresholdTimestamp,
                            $endTime
                        ]);
                        break;
                    default:
                        //小于
                        $query->where('add_customer_time', '<', $thresholdTimestamp);
                        break;
                }
                break;
            case 'last_send_msg_time':
                //最后发言时间
                $startTime = $value['start_time'];
                $endTime = $value['end_time'];
                switch ($op){
                    case 'later':
                        $query->where('last_send_msg_time','<',$startTime);
                        break;
                    case 'earlier':
                        $query->where('last_send_msg_time','>',$startTime);
                        break;
                    case 'range_within':
                        $query->whereBetween('last_send_msg_time',[$startTime,$endTime]);
                        break;
                    case 'out_of_range':
                        $query->whereNotBetween('last_send_msg_time',[$startTime,$endTime]);
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
    }
}